package com.zhuangjie.mvc.enhance.mp_query_enhance.operation;

import com.baomidou.mybatisplus.extension.service.IService;
import com.zhaungjie.base.utils.LambdaStructureParser.LambdaStructureParser;
import com.zhaungjie.base.utils.ReflectionUtils;
import com.zhuangjie.mvc.enhance.mp_query_enhance.enums.AggregationOperation;
import com.zhuangjie.mvc.enhance.mp_query_enhance.LambdaQueryWrapperPlus;
import com.zhuangjie.mvc.enhance.mp_query_enhance.LambdaQueryWrapperPlusHelper;
import com.zhuangjie.mvc.enhance.mp_query_enhance.ValueRef;
import com.zhuangjie.mvc.enhance.mp_query_enhance.entity.AggregatorMeta;
import com.zhuangjie.mvc.enhance.mp_query_enhance.utils.LambdaGetHashMap;

import java.util.*;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * LambdaQueryWrapperPlusHelper的forUse相关方法返回的操作对象
 *
 * @author zhuangjie
 * @date 2024/05/02
 */
public class ForUseOperation<E, R,IT> {
        private LambdaQueryWrapperPlus<E, R> wrapperPlus;
        private Map<LambdaStructureParser.NAHRFunction<E, Object>, Consumer<Object>> funConsumerMap;
        private List<AggregatorMeta> aggregatorMetaList;
        private Map<String, ValueRef> valueRefMap;

        public ForUseOperation(LambdaQueryWrapperPlus<E, R> wrapperPlus) {
            this.wrapperPlus = wrapperPlus;
        }

        public <CT> ForUseOperation<E, R,IT> use(AggregationOperation aggregationOperation, LambdaStructureParser.NAHRFunction<E, CT> fun, Consumer<ValueRef<IT>> valueRefConsumer) {
            if (aggregationOperation == null || fun == null || valueRefConsumer == null) {
                throw new RuntimeException("ForUseOperation.ForUseOperation.use：参数不能为空");
            }
            if (aggregatorMetaList == null) {
                aggregatorMetaList = new ArrayList<>();
            }
            if (valueRefMap == null) {
                valueRefMap = new HashMap<>();
            }
            String fieldName = LambdaStructureParser.convertToFieldName(fun);
            aggregatorMetaList.add(new AggregatorMeta(aggregationOperation, fieldName));
            ValueRef<IT> valueRef = new ValueRef<>();
            valueRefConsumer.accept(valueRef);
            valueRefMap.put(LambdaQueryWrapperPlus.getAggregationOperationAlias(aggregationOperation, fieldName), valueRef);
            return this;
        }

        public <CT> ForUseOperation<E, R,?> use(LambdaStructureParser.NAHRFunction<E, CT> fun, Consumer<CT> consumer) {
            if (funConsumerMap == null) {
                funConsumerMap = new HashMap<>();
            }
            funConsumerMap.put((LambdaStructureParser.NAHRFunction<E, Object>) fun, (Consumer<Object>) consumer);
            return this;
        }

        public <RT> void lastUse(LambdaStructureParser.NAHRFunction<E, RT> fun, Consumer<RT> consumer) {
            use(fun, consumer);
            // 要使用到的列名（属性名）
            Map<String, ? extends Consumer<Object>> fieldNameAndConsumerMap = funConsumerMap.entrySet().stream().collect(Collectors.toMap(entity -> LambdaStructureParser.convertToFieldName(entity.getKey()), Map.Entry::getValue));
            Set<String> useFields = fieldNameAndConsumerMap.keySet();
            wrapperPlus.selectForFieldName(useFields.toArray(new String[0]));
            // 调用“消费者”消费
            Class<E> entityClass = wrapperPlus.getEntityClass();
            IService<E> iServiceByEntityClass =  LambdaQueryWrapperPlusHelper.findIServiceByEntityClass(entityClass);
            if (iServiceByEntityClass == null) {
                throw new RuntimeException("ForUseOperation.lastUse未找到对应的IService，请检查是否使用非本模块的entity类！");
            }
            E entityInstance = iServiceByEntityClass.getOne(wrapperPlus);
            fieldNameAndConsumerMap.forEach((useFieldName, value) -> {
                // 获取r对象中fieldName属性值
                Object needUseValue = ReflectionUtils.getFieldValue(entityInstance, useFieldName);
                Consumer<Object> currentConsumer = fieldNameAndConsumerMap.get(useFieldName);
                currentConsumer.accept(needUseValue);
            });
        }


        public void inject(Function<LambdaGetHashMap<Object>, IT> fun) {
            // 解析为select sql
            wrapperPlus.selectForUseGroupBy(aggregatorMetaList);
            IService<E> service = LambdaQueryWrapperPlusHelper.findIServiceByEntityClass(wrapperPlus.getEntityClass());
            // 每一row有keys信息与聚合运算的column信息
            List<Map<String, Object>> rows = service.listMaps(wrapperPlus);
            if (rows == null || rows.isEmpty()) return;
            rows.forEach(row -> {
                // row提取出keys列（LambdaGetHashMap）
                LambdaGetHashMap<Object> keyColumnValueMap = new LambdaGetHashMap<>();
                HashMap<String, Object> aggColumnValueMap = new HashMap<>();
                Collection<String> groupByKeys = wrapperPlus.getGroupByKeyMap() == null ? new ArrayList<>() : wrapperPlus.getGroupByKeyMap().values();
                row.keySet().forEach(columnName -> {
                    if (groupByKeys.contains(columnName)) {
                        keyColumnValueMap.put(columnName, row.get(columnName));
                    } else {
                        aggColumnValueMap.put(columnName, row.get(columnName));
                    }
                });
                IT injectTarget = fun.apply(keyColumnValueMap);
                if (injectTarget == null) return;
                // 查询出来的row中的aggColumns : {aggColumn1: aggColumn1Value,...}
                aggColumnValueMap.forEach((aggColumnName, aggColumnValue) -> {
                    // aggColumnName 如：avgName
                    // row->column的值注入器
                    ValueRef valueRef = valueRefMap.get(aggColumnName);
                    if (valueRef == null) {
                        throw new RuntimeException("LambdaQueryWrapperPlusHelper.injet未找到对应的ValueRef");
                    }
                    valueRef.inject(injectTarget, aggColumnValue);
                });
            });
        }
    }